package martian.t1me.core
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	public class Queue extends EventDispatcher implements Sequencable, Pausable
	{
		public var stack:Vector.<Sequencable>;
			private var i:int = 0;
			private var l:int = 2;
				public function get limit():int { return l; }
				public function set limit(i:int):void
				{
					i = (i < 1) ? 1 : i;
					
					var d:int = l - i;
					
					l = i;
					
					if (s == Sequence.RUNNING && d > 0)
					{
						for (var a:int = 0; a < d; a++) { launch(); }
					}
				}
				
			private var p:Boolean = true;
			private var q:int = 0;
			private var s:int = 0;
				public function get status():int { return s; }
				
			private var t:int = 0;
		
		public function Queue(limit:int = 2, ...args)
		{
			l = limit;
			
			stack = new Vector.<Sequencable>();
			
			for each (var arg:* in args)
			{
				if (arg is Sequencable) { stack.push(arg); }
				else { trace("Warning:", arg, "does not implement Sequencable (skipped)"); }
			}
		}
		
		public function start():void
		{
			if (s == Sequence.STOPPED)
			{
				dispatchEvent(new Event(Sequence.START));
				
				i = 0;
				q = 0;
				t = 0;
				
				for (var a:int = 0; a < l; a++) { launch(); }
			}
		}
		
		private function launch():void
		{
			if (i < stack.length)
			{
				stack[i].addEventListener(Sequence.STOP, stop);
				stack[i].start();
				
				i++;
				q++;
			}
		}
		
		public function pause():void
		{
			if (s == Sequence.RUNNING)
			{
				p = true;
				s = Sequence.PAUSED;
			}
		}
		
		public function resume():void
		{
			if (s == Sequence.PAUSED)
			{
				p = false;
				for (var a:int = 0; a < l; a++) { launch(); }
				s = Sequence.RUNNING;
			}
		}
		
		private function stop(e:Event):void
		{
			e.target.removeEventListener(Sequence.STOP, stop);
			
			t++;
			q--;
			
			if (t == stack.length)
			{
				dispatchEvent(new Event(Sequence.STOP));
				s = Sequence.STOPPED;
			}
			else if (q < l)
			{
				var d:int = l - q;
				while(d-- > 0) { launch(); }
			}
		}
	}
}